//
//  XLCAudioRecorder.m
//  XLConversationInputView
//
//  Created by ilongge on 2022/8/31.
//
#import <AVFoundation/AVFoundation.h>
#import "XLCAudioRecorder.h"

#define AudioRecoderTimeStep 0.1

@interface XLCAudioRecorder()
<
AVAudioRecorderDelegate
>
@property (nonatomic, strong) AVAudioRecorder *audioRecorder;
@property (nonatomic, strong) NSTimer *recorderTimer;
@property (nonatomic, assign) float duration;
@end
@implementation XLCAudioRecorder

- (instancetype)initWithRootPath:(NSString *)rootPath
{
    self = [super init];
    if (self) {
        if (rootPath.length == 0) {
            NSString* cachesDirectory = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
            cachesDirectory = [cachesDirectory stringByAppendingPathComponent:[[NSBundle mainBundle] bundleIdentifier]];
            rootPath = [NSString stringWithFormat:@"%@/VoiceRecoredCache", cachesDirectory];
        }
        self.maxVoiceDuration = 60.f;
        self.minVoiceDuration = 2.0f;
        _rootPath = rootPath;
        NSFileManager *filemanager = [NSFileManager defaultManager];
        BOOL ret = [filemanager fileExistsAtPath:rootPath];
        if (ret == NO) {
            NSError *error = nil;
            BOOL result = [filemanager createDirectoryAtPath:rootPath
                                 withIntermediateDirectories:YES
                                                  attributes:@{}
                                                       error:&error];
            if (error || result == NO) {
                NSLog(@"create cache directory fail: %@", rootPath);
            }
        }
    }
    return self;
}

- (BOOL)startRecorddWithAVAudioRecorder
{
    if (self.audioRecorder) {
        AVAuthorizationStatus authStatus = [AVCaptureDevice authorizationStatusForMediaType:AVMediaTypeAudio];
        if (authStatus == AVAuthorizationStatusAuthorized) {
            if (self.recorderTimer == nil) {
                self.recorderTimer = [NSTimer timerWithTimeInterval:AudioRecoderTimeStep
                                                             target:self
                                                           selector:@selector(timeCount)
                                                           userInfo:nil
                                                            repeats:YES];
                [[NSRunLoop currentRunLoop] addTimer:self.recorderTimer forMode:NSRunLoopCommonModes];
            }
            [self.recorderTimer setFireDate:[NSDate distantPast]];
            BOOL ret = [self.audioRecorder prepareToRecord];
            if (ret) {
                ret = [self.audioRecorder record];
                if (ret) {
                    NSLog(@"record start success");
                }
                else {
                    NSLog(@"record start faile");
                }
            }
            else {
                NSLog(@"record start faile");
            }
            return ret;
        }
        else{
            [AVCaptureDevice requestAccessForMediaType:AVMediaTypeAudio
                                     completionHandler:^(BOOL granted) {
                if (granted) {
                    NSLog(@"Microphone enabled");
                }
                else{
                    NSLog(@"Microphone disabled");
                }
            }];
            return NO;
        }
    }
    return NO;
} 
- (BOOL)startRecord
{
    [self reinit];
    BOOL ret = [self startRecorddWithAVAudioRecorder];
    return ret;
}

- (void)timeCount {
    self.duration += AudioRecoderTimeStep;
    if (self.recordTimeBlock) {
        self.recordTimeBlock(self.duration);
    }
}
/// 删除录音recorder
- (BOOL)cancleRecorder {
    [self.audioRecorder pause];
    [self.audioRecorder stop];
    BOOL ret = [self.audioRecorder deleteRecording];
    [self reinit];
    return ret;
}

- (void)reinit {
    if (self.recorderTimer) {
        [self.recorderTimer invalidate];
        self.recorderTimer = nil;
    }
    self.duration = 0.0f;
    self.audioRecorder = nil;
}
/// 结束录音
- (NSURL *)stopRecorder {
    [self.audioRecorder pause];
    [self.audioRecorder stop];
    NSLog(@"record duration：%.1lf 秒", self.duration);
    NSURL *url;
    /// 时间太短
    if (self.duration < self.minVoiceDuration) {
        [self.audioRecorder deleteRecording];
        url = [NSURL URLWithString:@"error://durationTooShort"];
        NSLog(@"record duration too low");
    }
    else{
        url = self.audioRecorder.url.copy;
        NSLog(@"recoderFilePath：%@", url.path);
        NSDictionary *attribute = [[NSFileManager defaultManager] attributesOfItemAtPath:url.path
                                                                                   error:nil];
        NSNumber *fileSize = attribute[@"NSFileSize"];
        NSLog(@"recoderFileSize：%ld KB", (long)(fileSize.integerValue / 1024.0));
    }
    [self reinit];
    return url;
}

- (NSURL *)currentVoiceUrl
{
    NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    formatter.dateFormat = @"yyyy_MM_dd_HH_mm_ss_SSS";
    NSString *timeString = [formatter stringFromDate:[NSDate date]];
    NSString *filePath = [NSString stringWithFormat:@"%@/Voice_%@_recorder.wav", self.rootPath, timeString];
    NSURL *currentVoiceUrl = [NSURL fileURLWithPath:filePath];
    return currentVoiceUrl;
}
- (AVAudioRecorder *)audioRecorder {
    if (_audioRecorder == nil) {
        NSError *error;
        AVAudioSession *session = [AVAudioSession sharedInstance];
        [session setCategory:AVAudioSessionCategoryPlayAndRecord
                        mode:AVAudioSessionModeDefault
                     options:AVAudioSessionCategoryOptionDefaultToSpeaker|AVAudioSessionCategoryOptionAllowBluetooth|AVAudioSessionCategoryOptionAllowBluetoothA2DP
                       error:&error];
        if (error) {
            NSLog(@"setCategory error");
            return nil;
        }
        NSURL *audioUrl = [self currentVoiceUrl];
        _audioRecorder = [[AVAudioRecorder alloc] initWithURL:audioUrl
                                                     settings:self.recorderParams
                                                        error:&error];
        if (error) {
            NSLog(@"init audioRecorder error : %@", error.localizedDescription);
            _audioRecorder = nil;
        }
        else{
            NSLog(@"init audioRecorder success : %@", audioUrl);
            _audioRecorder.delegate = self;
        }
    }
    return _audioRecorder;
}

- (NSDictionary *)recorderParams
{
    if(_recorderParams == nil) {
        _recorderParams = @{
            AVFormatIDKey: @(kAudioFormatLinearPCM),
            AVSampleRateKey: @(8000.0),
            AVNumberOfChannelsKey: @(1),
            AVAudioFileTypeKey:@(kAudioFileWAVEType),
            AVEncoderBitDepthHintKey: @(16),
            AVEncoderAudioQualityKey: @(AVAudioQualityHigh)
        };
    }
    return _recorderParams;
}

- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
    NSLog(@"audioRecorderDidFinishRecording:%d", flag);
}

- (void)audioRecorderEncodeErrorDidOccur:(AVAudioRecorder *)recorder error:(NSError *)error
{
    NSLog(@"audioRecorderEncodeErrorDidOccur:%@", error);
}
@end
